#include "ui_state.h"
#include "ui_popup.h"

#include "game_flow_manager.h"
#include "application/game_application.h"
#include "camera/fb_camera.h"
#include "console/console.h"
#include "font/font_manager.h"
#include "font/font.h"
#include "input/mouse.h"
#include "audio/audio.h"

#include "ui/ui_manager.h"
#include "resman/resman.h"
#include "camera/fb_camera.h"
#include "dd/dd_man.h"
#include "graphics/graphics.h"

#include "vfs/vfs.h"

#include "util/timer.h"				// log
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    

#include <cassert>
using namespace gameflow;

 bool		UIState::m_Donot_look_for_bganim_lua = false;

UIState::UIState(camera::FbCamera*	pCamera, const std::string& BasePanel, const std::string& ExecuteOnEnter,  const std::string& ExecuteOnLeave) :
	gameflow::GameState(),
	input::MouseListener(),
	input::KeyboardListener(),
	m_pCamera(pCamera),
	m_OnEnter(ExecuteOnEnter),
	m_OnLeave(ExecuteOnLeave),
	m_CurrentIdx(0),
	m_pLastMouseDownWidget(NULL),
	m_BGScale(1.0f),
	m_MOGAStatusDealyDisconnect(0),
	m_MOGAStatusDealyConnect(0),
	m_NextMOGATestKeyReady(true),
	m_MOGALastState(false)
{
	input::MouseListener::Disable();
	input::KeyboardListener::Disable();
	if (!BasePanel.empty())
	{
		m_PanelFiles.push_back(BasePanel);
		LoadPanel(BasePanel);
	}
}

UIState::~UIState()
{
}

void		UIState::LoadPanel(const std::string& File, bool ClearAll)
{
	if (ClearAll)
	{
		m_Panels.resize(0);
	}
	ui::UIWidget* pWidget = ui::UIManager::Instance().AddPanel(File);
	if (pWidget)
	{
		pWidget->SetIsVisible(false);
		m_Panels.push_back(pWidget);

		// check if there's a BasePanel LUA file with animations as well
		if(!m_Donot_look_for_bganim_lua)
		{
			std::string	Base = vfs::VFS::StripExtension(File);
			m_BG.Load(Base+".lua");
		}
	}
}

ui::UIWidget*	UIState::GetWidget(const std::string& Name)
{
	for (unsigned int i=0; i<m_Panels.size(); i++)
	{	
		ui::UIWidget*	pWidget = m_Panels[i]->GetWidgetByName(Name);
		if (pWidget) return pWidget;
	}
	_LOG(MSG_ERROR, "No ui Widget " << Name << " exists in the panel/state " << m_Name);
	return NULL;
}

void		UIState::SetMusic(const std::string& Music)
{
	m_Music = Music;
}

bool		UIState::OnEnter()
{
	GameState::OnEnter();
	for (int i=0; i<(int)m_Panels.size(); i++)
	{
		m_Panels[i]->SetIsVisible(true);
	}
	if (!m_Music.empty())
		AUDIO().PlayMusic(m_Music);

	PostInitUI();

	if (!m_OnEnter.empty())
		ui::UIManager::Instance().ExecuteScript(m_OnEnter);


	//m_FadeSprite.Create("ui_img/fade_bg.png");
	//m_FadeSprite.Setup(math::Vec2(0,0), math::Vec2(1,1));

	if (m_pCamera)
	{
		ui::UIManager::Instance().SetCamera(m_pCamera);
		m_pCamera->SetLookAt(math::Vec3(00, 0, -20), math::Vec3(0, 0, 000), math::Vec3(0,1,0));
	}

	input::KeyboardListener::Enable();
	input::MouseListener::Enable();
    
#if defined(_PLATFORM_ANDROID) || defined(_PLATFORM_WIN32)
	input::MOGAJoystick::Instance().SetListener(this);
#endif

	return true;
}

bool		UIState::OnExit()
{
	GameState::OnExit();
	input::MouseListener::Disable();
	input::KeyboardListener::Disable();

	for (unsigned int i=0; i<m_Panels.size(); i++)
	{
		m_Panels[i]->SetIsVisible(false);
	}

	if (!m_OnLeave.empty())
		ui::UIManager::Instance().ExecuteScript(m_OnLeave);



	return true;
}

bool		UIState::Tick(float dt)
{
	GameState::Tick(dt);
	m_BG.Tick(dt);
	if (m_BG.GetEditor())
	{
		m_BG.UpdateScroll(GET_MOUSE().GetPos(), TIMER().Delta());
	}
	if (!m_Panels.empty() && m_Panels[0])
	{
		m_Panels[0]->SetIsActive(!m_BG.GetEditor());//, false);
	}
	ui::UIManager::Instance().Tick(dt);

	if (m_pCamera) 	m_pCamera->Tick(dt);

	if(m_MOGAStatusDealyConnect > 0)
	{
		m_MOGAStatusDealyConnect  -= dt;
	}

	if(m_MOGAStatusDealyDisconnect > 0)
	{
		m_MOGAStatusDealyDisconnect -= dt;
	}

	return true;
}

bool		UIState::AddPanel(const std::string& Panel)
{
	if (!Panel.empty())
		m_PanelFiles.push_back(Panel);

	// add deferred (i.e. don't load now)
	ui::UIWidget* pWidget = ui::UIManager::Instance().AddPanel(Panel);
	if (pWidget)
		m_Panels.push_back(pWidget);

	return true;
}

void	UIState::RenderFade()
{
	// is it cleaner to do this as a seperate pass? Expensive, though.
	GameFlowManager::Instance().GetTransition().Render();
}
bool		UIState::Render()
{

	if (!m_pCamera->StartFrame()) return false;

	GetGraphics()->Start2D();

	m_BG.RenderBackground(m_BGScale);
	PreRender();
	// draw any loose font data
	bool	UseFilter = GetGraphics()->GetFilter2D();
	GetGraphics()->SetFilter2D(true);
	ui::UIManager::Instance().Render();
	m_BG.RenderForeground(m_BGScale);
	PostRender();

	console::Console::Instance().Render();
	FontManager::Instance().RenderCache();
	
//	FontManager::Instance().SetColor(ColorRGBA(55, 55, 55));


	GetGraphics()->SetFilter2D(UseFilter);
	dd::Manager::Instance().Render2D();

	RenderFade();

	if(m_MOGAStatusDealyConnect > 0)
	{
		FontManager::Instance().PrintCentered(math::Vec2(0.5f,0.1f), "Controller Status: Connected" );
	}
	else if(m_MOGAStatusDealyDisconnect > 0)
	{		
		FontManager::Instance().PrintCentered(math::Vec2(0.5f,0.1f), "Controller Status: Disconnected" );		
	}

	// end frame
	m_pCamera->EndFrame();
	bool Success = m_pCamera->Show();
 	return Success;
}
void	UIState::SetPanelVisible(const std::string& Name, bool Vis)
{
	ui::UIManager& UIMan = ui::UIManager::Instance();
	ui::UIWidget* pWidget = UIMan.GetPanel(Name); 
	if (pWidget) pWidget->SetIsVisible(Vis);
}


void		UIState::KeyDown(input::Keyboard::KEY* pKey)
{
	if(m_NextMOGATestKeyReady)
	{
	// for eaier testing 
		int MOGAKeyCode = -1;
		if(pKey->KeyID == KEY_LEFT)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_DPAD_LEFT;
		else if(pKey->KeyID == KEY_RIGHT)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_DPAD_RIGHT;
		else if(pKey->KeyID == KEY_DOWN)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_DPAD_DOWN;
		else if(pKey->KeyID == KEY_UP)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_DPAD_UP;
		else if(pKey->KeyID == KEY_ESCAPE || pKey->KeyID == KEY_B)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_BUTTON_B;
		else if(pKey->KeyID == KEY_A )
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_BUTTON_A;
		else if(pKey->KeyID == KEY_RETURN)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_BUTTON_START;
		else if(pKey->KeyID == KEY_X)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_BUTTON_X;
		else if(pKey->KeyID == KEY_Y)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_BUTTON_Y;
		else if(pKey->KeyID == KEY_R)
			MOGAKeyCode = input::MOGAJoystick::KEYCODE_BUTTON_R2;

		if(MOGAKeyCode > 0)
			m_NextMOGATestKeyReady = false;

		input::MOGAJoystick::Instance().OnMOGAKeyDownEvent(MOGAKeyCode);
	}

	m_BG.KeyDown(pKey);
}

void		UIState::KeyPressed(input::Keyboard::KEY* pKey)
{
	m_NextMOGATestKeyReady = true; 
	m_BG.KeyPressed(pKey);
}
void		UIState::MouseMove(const math::Vec2& From, const math::Vec2& To)
{
	m_BG.MouseMove(From, To);
}

void	UIState::MouseButtonReleased(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	m_pLastMouseDownWidget = NULL;
	m_BG.MouseButtonReleased(pKey, Pos);
}

void	UIState::MouseButtonPressed(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	
	m_BG.MouseButtonPressed(pKey, Pos);

}

void	UIState::MouseButtonDown(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
		
}

void	UIState::MouseWheelMove(int WheelInfo, const math::Vec2& Pos)
{
	m_BG.MouseWheelMove(WheelInfo, Pos);
}


void	UIState::SetWidgetFunctor(const std::string& Widget, ui::UIWidget::tdgEvent Event, ui::UIWidget::WIDGET_EVENT EventID)
{
	ui::UIWidget*	pWidget = GetWidget(Widget);
	if (!pWidget)	return;
	// check if one already exists?
	pWidget->SetEventDg(EventID, Event);

	// chit: ios needs this
	//if(EventID == ui::UIWidget::WE_LMB_RELEASE)
	//{
	//	SetWidgetFunctor(Widget,UI_DELEGATE(UIState, OnMousePressedOnWidget),EventID);
	//}
}

void DELEGATE_CALL	UIState::OnMousePressedOnWidget(ui::UIWidget::WIDGET_EVENT Event, ui::UIWidget* pWidget)
{
	m_pLastMouseDownWidget = pWidget;	

}

ui::UIWidget*		UIState::GetLastMouseClickWidget(ui::UIWidget* pMouseUpWidget) 
{
	ui::UIWidget* Temp = m_pLastMouseDownWidget;
	if( pMouseUpWidget == m_pLastMouseDownWidget)
		m_pLastMouseDownWidget = NULL;

	return Temp; 
}


void				UIState::DPadNav(int	DirX, int DirY, int	Triggered)
{
	if (!m_PrevMenu.empty() && Triggered == -1)	// go back if possible
	{
		GoPrevMenu();
		return;
	}

	if (m_NavList.empty()) return;
	ui::UIWidget*	pOld = m_NavList[m_CurrentIdx];
	if (DirY != 0)
	{
		m_CurrentIdx+=DirY;
		if (m_CurrentIdx < 0) m_CurrentIdx =(int) m_NavList.size()-1;
		if (m_CurrentIdx >= (int)m_NavList.size()) m_CurrentIdx = 0;
	}

	ui::UIWidget*	pElement = m_NavList[m_CurrentIdx];
	if (!pElement) return;
//	pOld->SetState(ui::UIWidget::WS_MOUSE_OFF);
//	pElement->SetState(ui::UIWidget::WS_MOUSE_OVER);
	ui::UIManager::Instance().SetSelected(pElement);

	if (Triggered == 1)	// activate current
	{
		pElement->TriggerEvent(ui::UIWidget::WE_LMB_RELEASE);
	} 
	if (DirX == -1)	// activate current
	{
		pElement->TriggerEvent(ui::UIWidget::WE_LEFT_KEY);
	}
	if (DirX ==  1)	// activate current
	{
		pElement->TriggerEvent(ui::UIWidget::WE_RIGHT_KEY);
	}
}

void	UIState::SetWidgetText(const std::string& Name, const std::string& Text)
{
	ui::UIWidget*	pWidget = GetWidget(Name);
	if (!pWidget)	return;
	pWidget->SetTextA(Text);
}

void	UIState::SetWidgetPopup(const std::string& WidgetName, const std::string& PopupName, 
								GameTransition::TransitionEvent		OnStart, 
								ui::UIMover::MoverEvent	OnFinish)

{
	ui::UIWidget*	pWidget = GetWidget(WidgetName);
	UIPopupManager::Instance().SetWidgetPopup(pWidget, PopupName, OnStart, OnFinish);
}


void	UIState::SetupTransition(const std::string& Widget, 
								const std::string& ToState, 
								const std::string& Sound, 
								GameTransition::TransitionEvent		OnStart, 
								GameTransition::TransitionEvent	OnFinish)
{
	ui::UIWidget*	pWidget = GetWidget(Widget);
	if (!pWidget)
	{
		_LOG(MSG_ERROR, "No ui Widget " << Widget << " exists in the panel/state " << m_Name);
		return;
	}
	GameFlowManager::Instance().GetTransition().SetupTransitionDg(pWidget, ToState, Sound, OnStart, OnFinish);
}

void		UIState::OnMOGAStateEvent(int	State)
{
	if( input::MOGAJoystick::Instance().IsConnected() == true)
	{
		m_MOGAStatusDealyConnect = 2.0f;
		m_MOGALastState = true;
	}
	else if ( m_MOGALastState == true)
	{
		m_MOGAStatusDealyDisconnect = 2.0f;
		m_MOGALastState = false;


	}
}